package cc.togetherit.jcrawler.slot;

import java.util.ArrayList;
import java.util.List;

import org.apache.commons.lang3.StringUtils;
import org.apache.log4j.Logger;

import cc.togetherit.jcrawler.checkRepeat.MemRepeatCheck;
import cc.togetherit.jcrawler.checkRepeat.RepeatCheck;
import cc.togetherit.jcrawler.crawler.CrawlerConfig;
import cc.togetherit.jcrawler.crawler.CrawlerContext;
import cc.togetherit.jcrawler.crawler.JdkXpathMemPoolCrawlerContenxt;
import cc.togetherit.jcrawler.parser.SiteParser;
import cc.togetherit.jcrawler.util.ThreadPoolUtil;
import cc.togetherit.jcrawler.util.XMLutil;

public class DefaultSlot implements Slot {

    Logger logger = Logger.getLogger(getClass());
    CrawlerContext context;
    CrawlerConfig config;
    private int parseTheradcount = 1;
    private int fetchThreadCount = 1;
    private int persistenceThreadCount = 1;
    private int downThreadCount = 1;
    private RepeatCheck repeat;
    private SiteParser parser;


    private List<String> feeds = new ArrayList<String>();;



    public DefaultSlot(CrawlerContext context, CrawlerConfig config, RepeatCheck repeat) {
        super();
        this.context = context;
        this.config = config;
        this.repeat = repeat;
    }

    public DefaultSlot(RepeatCheck repeat) {
        super();
        this.config = new CrawlerConfig();
        this.repeat = repeat;
        // context = new JdkXpathMemPoolCrawlerContenxt(config);
    }


    public DefaultSlot() {
        this.config = new CrawlerConfig();
        // context = new JdkXpathMemPoolCrawlerContenxt(config);
        // context.setConfig(config);
        this.repeat = new MemRepeatCheck();
    }


    public Slot addFeed(String... url) {
        for (String u : url) {
            feeds.add(u);
        }
        return this;
    }

    public Slot fetchThread(int count) {
        this.fetchThreadCount = count;
        return this;
    }

    public Slot parseThread(int count) {

        this.parseTheradcount = count;
        return this;
    }

    public Slot persistenceThread(int count) {
        this.persistenceThreadCount = count;
        return this;
    }

    public Slot LoadConfig(String path) {
        if (StringUtils.isEmpty(path)) {
            logger.error("path is empty !!!");
            logger.error("use default config");
            config.defaultConfig();
        }
        XMLutil.loadConfig(path, config);
        return this;
    }



    public CrawlerConfig getConfig() {
        return config;
    }


    public void setConfig(CrawlerConfig config) {
        this.config = config;
    }


    public RepeatCheck getRepeat() {
        return repeat;
    }


    public void setRepeat(RepeatCheck repeat) {
        this.repeat = repeat;
    }


    public Slot setParser(SiteParser parser) {
        // context.getParseEngine().setParser(parser);
        this.parser = parser;
        return this;
    }

    public SiteParser getParser() {
        return parser;
    }

    public Slot setRepeatCheck(RepeatCheck check) {
        context.getFetchEngine().setCheck(check);
        return this;
    };

    public void begin() {
        if (!checkConfig()) {
            return;
        };
        if (context == null) {
            initContext(config);
        } else {
            context.setConfig(config);
        }

        if (context.getParseEngine().getParser() == null) {
            System.out.println("parser is NULL!!!");
            return;
        }

        context.addFeed(feeds.toArray(new String[] {}));
        for (int i = 0; i < persistenceThreadCount; i++) {
            ThreadPoolUtil.execute(context.getPersitenceEngine(), true, "persistenceEngine");
        }
        for (int i = 0; i < parseTheradcount; i++) {
            ThreadPoolUtil.execute(context.getParseEngine(), true, "parseEngine");
        }
        for (int i = 0; i < fetchThreadCount; i++) {
            ThreadPoolUtil.execute(context.getFetchEngine(), true, "fetchEngine");
        }
        for (int i = 0; i < downThreadCount; i++) {
            ThreadPoolUtil.execute(context.getDownEngine(), true, "downEngine");
        }
    }

    private void initContext(CrawlerConfig config2) {
        context = new JdkXpathMemPoolCrawlerContenxt(config2);
        context.setConfig(config2);
        context.getParseEngine().setParser(parser);
        context.getPersitenceEngine().setParser(parser);
        // context.build();
    }

    private boolean checkConfig() {
        if (config == null) {
            logger.error("config is null !!!!");
            return false;
        }
        return true;
    }

    public CrawlerContext getContext() {
        return context;
    }

    public void setContext(CrawlerContext context) {
        this.context = context;
    }

    public Slot downThread(int count) {
        this.downThreadCount = count;
        return this;
    }

}
